package org.sfx.diagnostics

import javafx.beans.value.ObservableValue
import javafx.collections.ObservableList
import javafx.scene.control.Control
import javafx.scene.control.Label
import javafx.scene.control.TreeCell
import javafx.scene.input.MouseButton
import javafx.scene.layout.Region
import javafx.scene.layout.Pane
import javafx.scene.Node
import javafx.scene.Scene
import org.sfx.rich.Enrich._
import org.sfx.util.Capabilities.CanAddRemoveChangeListener
import javafx.scene.layout.HBox
import javafx.scene.control.TextField
import javafx.event.EventHandler
import javafx.scene.input.KeyEvent
import javafx.scene.input.KeyCode

class SpyCell extends TreeCell[SpyInfo] {
  val icon = new Label()
  val nameLabel = new Label()
  val valueLabel = new Label()
  val content = new HBox() {
    this.getChildren().addAll(valueLabel)
  }
  var editBox: Option[TextField] = None
  val treeNode = new HBox {
    this.getChildren().addAll(icon, nameLabel, content)
  }
  
  this.setGraphic(treeNode)
  
  override def startEdit(): Unit = {
    println("--> startEdit")
    super.startEdit()
    val editBox = new TextField() {
      this.setOnKeyPressed(new EventHandler[KeyEvent]() {
        override def handle(keyEvent: KeyEvent): Unit = {
          keyEvent.getCode() match {
            case KeyCode.ENTER => {
              SpyCell.this.commitEdit(SpyCell.this.getItem())
              keyEvent.consume()
            }
            case KeyCode.ESCAPE => {
              SpyCell.this.cancelEdit()
              keyEvent.consume()
            }
            case _ =>
          }
        }
      })
    }
    this.editBox = Some(editBox)
    content.getChildren.setAll(editBox)
    editBox.requestFocus()
  }
  
  override def commitEdit(spyInfo: SpyInfo): Unit = {
    this.editBox match {
      case None =>
      case Some(editBox) => {
        println("--> new value: " + editBox.textProperty().get())
        spyInfo.stringValue = editBox.textProperty().get()
      }
    }
    content.getChildren.setAll(valueLabel)
    super.commitEdit(spyInfo)
  }
  
  override def cancelEdit(): Unit = {
    content.getChildren.setAll(valueLabel)
    super.cancelEdit()
  }
  
  def applyKindStyle(kind: SpyKind): Unit = kind match {
    case SpyKind.WritableProperty => {
      icon.setText("P")
      icon.setStyle("-fx-text-fill: green; -fx-font-weight: bold;")
      setEditable(true)
    }
    case SpyKind.ReadableProperty => {
      icon.setText("P")
      icon.setStyle("-fx-text-fill: red; -fx-font-weight: bold;")
      setEditable(false)
    }
    case SpyKind.ObservableList => {
      icon.setText("P")
      icon.setStyle("-fx-text-fill: purple; -fx-font-weight: bold;")
      setEditable(false)
    }
    case SpyKind.ReadableValue => {
      icon.setText("V")
      setEditable(false)
    }
  }

  override def updateItem(spyInfo: SpyInfo, empty: Boolean): Unit = {
    super.updateItem(spyInfo, empty)
    
    if (spyInfo == null) {
      setText("null")
    } else {
      applyKindStyle(spyInfo.kind)
      this.nameLabel.setText(spyInfo.name + ":")
      this.valueLabel.setText(spyInfo.itemString)
      spyInfo.item match {
        case null =>
        case observableValue: ObservableValue[_] => {
          observableValue.addChangeListener { (_, _, newValue) => this.valueLabel.setText(spyInfo.itemString) }
        }
        case _ =>
      }
    }
  }
  
  this.onMouseClicked { mouseEvent =>
    if (mouseEvent.getButton() == MouseButton.SECONDARY) {
    }
  }
  
  var updateText: () => Unit = { () => }
}
